part of 'updatable.dart';

extension DataStorerExtension on DataStorer {
  void initValues(List<Object> values) {
    for (var value in values) {
      if (value is StorableMixin) value.dataStorer = this;
    }
  }

  void initStorableDatas(List<StorableMixin> storableDatas) {
    for (var storableData in storableDatas) {
      storableData.dataStorer = this;
    }
  }

  void initStorableData(StorableMixin storableData) {
    storableData.dataStorer = this;
  }
}

extension UpdatableStateExtension<T> on T {
  UpdatableState<T> get updatableState => UpdatableState(initValue: this);
}

extension StorableStateExtension<T> on T {
  StorableState<T> toStorableState(
          {required String storeKey, DataStorer? dataStorer}) =>
      StorableState(initValue: this, storeKey: storeKey)
        ..dataStorer = dataStorer;
}

extension DatabaseStateListExtension on List<DatabaseState> {
  void initSaveFunction(Function() save) {
    for (final state in this) {
      state._save = save;
    }
  }
}

extension UpdatableListExtension<E> on List<E> {
  UpdatableList<E> get asUpdatable => UpdatableList<E>(this);
}

extension UpdatableMapExtension<K, V> on Map<K, V> {
  UpdatableMap<K, V> get asUpdatable => UpdatableMap<K, V>(this);
}

extension IntValueExtension on int {
  StateInt toState({required Object storeKey, bool? autoSave}) =>
      StateInt(initValue: this, storeKey: storeKey, autoSave: autoSave);
  UpdatableState<int> get updatableState => UpdatableState(initValue: this);
}

extension StringValueExtension on String {
  StorableState<String> toState({required Object storeKey, bool? autoSave}) =>
      StorableState(initValue: this, storeKey: storeKey, autoSave: autoSave);
  UpdatableState<String> get updatableState => UpdatableState(initValue: this);
}

extension DoubleValueExtension on double {
  StateDouble toState({required Object storeKey, bool? autoSave}) =>
      StateDouble(initValue: this, storeKey: storeKey, autoSave: autoSave);
  UpdatableState<double> get updatableState => UpdatableState(initValue: this);
}

extension BoolValueExtension on bool {
  StorableState<bool> toState({required Object storeKey, bool? autoSave}) =>
      StorableState(initValue: this, storeKey: storeKey, autoSave: autoSave);
  UpdatableState<bool> get updatableState => UpdatableState(initValue: this);
}

extension NumStateValueExt<T extends num> on StorableState<T> {
  num operator *(num other) => value * other;
  num operator %(num other) => value % other;
  double operator /(num other) => value / other;
  int operator ~/(num other) => value ~/ other;
  num operator -() => -value;
  num remainder(num other) => value.remainder(other);
  bool operator <(num other) => value < other;
  bool operator <=(num other) => value <= other;
  bool operator >(num other) => value > other;
  bool operator >=(num other) => value >= other;
  bool get isNaN => value.isNaN;
  bool get isNegative => value.isNegative;
  bool get isInfinite => value.isInfinite;
  bool get isFinite => value.isFinite;
  num abs() => value.abs();
  num get sign => value.sign;
  int round() => value.round();
  int floor() => value.floor();
  int ceil() => value.ceil();
  int truncate() => value.truncate();
  double roundToDouble() => value.roundToDouble();
  double floorToDouble() => value.floorToDouble();
  double ceilToDouble() => value.ceilToDouble();
  double truncateToDouble() => value.truncateToDouble();
  num clamp(num lowerLimit, num upperLimit) =>
      value.clamp(lowerLimit, upperLimit);
  int toInt() => value.toInt();
  double toDouble() => value.toDouble();
  String toStringAsFixed(int fractionDigits) =>
      value.toStringAsFixed(fractionDigits);
  String toStringAsExponential([int? fractionDigits]) =>
      value.toStringAsExponential(fractionDigits);
  String toStringAsPrecision(int precision) =>
      value.toStringAsPrecision(precision);
}

extension IntStateValueExt on StorableState<int> {
  int operator &(int other) => value & other;
  int operator |(int other) => value | other;
  int operator ^(int other) => value ^ other;
  int operator ~() => ~value;
  int operator <<(int shiftAmount) => value << shiftAmount;
  int operator >>(int shiftAmount) => value >> shiftAmount;
  int modPow(int exponent, int modulus) => value.modPow(exponent, modulus);
  int modInverse(int modulus) => value.modInverse(modulus);
  int gcd(int other) => value.gcd(other);
  bool get isEven => value.isEven;
  bool get isOdd => value.isOdd;
  int get bitLength => value.bitLength;
  int toUnsigned(int width) => value.toUnsigned(width);
  int toSigned(int width) => value.toSigned(width);
  int operator -() => -value;
  int abs() => value.abs();
  int get sign => value.sign;
  int round() => value.round();
  int floor() => value.floor();
  int ceil() => value.ceil();
  int truncate() => value.truncate();
  double roundToDouble() => value.roundToDouble();
  double floorToDouble() => value.floorToDouble();
  double ceilToDouble() => value.ceilToDouble();
  double truncateToDouble() => value.truncateToDouble();
}

extension DoubleStateValueExt on StorableState<double> {
  double operator *(num other) => value * other;
  double operator %(num other) => value % other;
  double operator /(num other) => value / other;
  int operator ~/(num other) => value ~/ other;
  double operator -() => -value;
  double abs() => value.abs();
  double get sign => value.sign;
  int round() => value.round();
  int floor() => value.floor();
  int ceil() => value.ceil();
  int truncate() => value.truncate();
  double roundToDouble() => value.roundToDouble();
  double floorToDouble() => value.floorToDouble();
  double ceilToDouble() => value.ceilToDouble();
  double truncateToDouble() => value.truncateToDouble();
}
